#include <string>
#include <iostream>
#include <sstream>
#include <vector>

#include "baseCard.h"
#include "baseToken.h"
#include "basePlayer.h"
#include "baseBoard.h"
#include "baseEffect.h"

class basePlayer;
class baseToken;
class baseBoard;

using namespace std;

baseCard::baseCard(string aName, int aCcost, int aPoint, baseBoard* aBaseBoard, int aId) : name(aName), cost(aCcost), point(aPoint), board(aBaseBoard), effect(NULL), owner(NULL), id(aId)
{
    tokenList.clear();
}

baseCard::baseCard(string aName, int aCcost, int aPoint, baseEffect* aEffect, baseBoard* aBaseBoard, int aId) : name(aName), cost(aCcost), point(aPoint), board(aBaseBoard), effect(aEffect), owner(NULL), id(aId)
{
    tokenList.clear();
    effect->setHostCard(this);
}

string baseCard::getName()
{
    return name;
}

int baseCard::getCost()
{
    return cost;
}

int baseCard::getPoint()
{
    return point;
}

basePlayer* baseCard::getOwner()
{
    return owner;
}

void baseCard::setOwner(basePlayer* aOwner)
{
    owner = aOwner;
}

int baseCard::getId()
{
    return id;
}

baseBoard* baseCard::getBoard()
{
    return board;
}

string baseCard::toString()
{
    stringstream out;

    out << getName() << " " << getCost() << " " << getPoint() << endl;

    out << tokenListToString();

    return out.str();
}

void baseCard::toString(ostream &out)
{
    out << toString();
}

void baseCard::toString(string &str)
{
    str = str + toString();
}

bool baseCard::isPayed(string aColor)
{
    int payed = 0;

    list<baseToken>::iterator lit(tokenList.begin()), lend(tokenList.end());
    for(;lit!=lend;++lit)
    {
        if(0 == lit->getColor().compare(aColor))
        {
            payed += 2*lit->getValue();
        }
        else
        {
            payed += lit->getValue();
        }
    }

    return payed >= (cost + board->getCostModifier(*this));
}

bool baseCard::operator== (baseCard aBaseCard)
{
    return id == aBaseCard.getId();
}

void baseCard::receiveToken(baseToken aToken)
{
    tokenList.push_back(aToken);
}

baseToken* baseCard::takeToken(string aColor)
{
    baseToken *res = NULL;

    list<baseToken>::iterator lit(tokenList.begin()), lend(tokenList.end());
    for(;lit!=lend;++lit)
    {
        if(0 == lit->getColor().compare(aColor))
        {
            res = &(*lit);
        }
    }

    return res;
}

list<baseToken>& baseCard::getTokenList()
{
    return this->tokenList;
}

baseEffect* baseCard::getEffect()
{
    return effect;
}

string baseCard::tokenListToString()
{
    stringstream out;

    list<baseToken>::iterator lit(tokenList.begin()), lend(tokenList.end());
    for(;lit!=lend;++lit) out << lit->toString() << endl;

    return out.str();
}

void baseCard::giveBackTokens()
{    
    list<baseToken>::iterator lit(tokenList.begin()), lend(tokenList.end());
    for(;lit!=lend;)
    {
        lit->getOwner()->receiveToken(*lit);
        lit = tokenList.erase(lit);
    }
}

void baseCard::getTokenColors(vector<string>& out)
{
    list<baseToken>::iterator lit(tokenList.begin()), lend(tokenList.end());
    for(;lit!=lend;++lit)
    {
        bool toAdd = true;
        for(unsigned int i=0; i<out.size(); i++)
        {
            if(out[i].compare(lit->getColor())==0)
            {
                toAdd = false;
            }
        }

        if(toAdd)
            out.push_back(lit->getColor());
    }
}

int baseCard::countTokens(string aColors)
{
    int res = 0;

    list<baseToken>::iterator lit(tokenList.begin()), lend(tokenList.end());
    for(;lit!=lend;++lit)
    {
        if(lit->getColor().compare(aColors) == 0)
            res ++;
    }

    return res;
}
